﻿using System;
using System.Runtime.Remoting;
using Needle.Utils;

namespace Needle.Core.Factory
{
    /// <summary>
    /// This factory creates instances in the AppDomain it is configured with.
    /// </summary>
    public class RemoteDomainFactory : FactoryBase
    {

        private AppDomain remoteDomain;
        /// <summary>
        /// Initializes a RemoteDomainFactory with the supplied AppDomain.
        /// </summary>
        public RemoteDomainFactory(AppDomain remoteDomain, Type producedType)
            : base(producedType)
        {
            Ensure.NotNull(remoteDomain, "remoteDomain");
            this.remoteDomain = remoteDomain;
            this.remoteDomain.DomainUnload += OnDomainUnload;
        }

        private void OnDomainUnload(object sender, EventArgs e)
        {
            remoteDomain = null;
        }
        /// <summary>
        /// Creates an instance of Type t with the default constructor in the remote AppDomain.
        /// </summary>
        public override object CreateInstance(params object[] args)
        {
            if (args != null && args.Length != 0)
                throw new NotSupportedException("This factory does not support creating instances with a non-default constructor");
            if (remoteDomain == null || remoteDomain.IsFinalizingForUnload() )
                throw new InvalidOperationException("Remote domain has unloaded.");
            ObjectHandle handle = Activator.CreateInstance(remoteDomain, ProducedType.Assembly.GetName().Name, ProducedType.FullName);
            Object instance = handle.Unwrap();
            return instance;
        }

    }

}
